package container

import "fmt"

type List[V comparable] struct {
	value []V
	len   int
	maps  map[V]struct{} // 用于判断是否包含某个元素
}

func NewList[V comparable]() *List[V] {
	return &List[V]{
		maps: make(map[V]struct{}),
	}
}

func (l *List[V]) Len() int {
	return l.len
}

func (l *List[V]) Append(value V) {
	l.value = append(l.value, value)
	l.maps[value] = struct{}{}
	l.len++
}

func (l *List[V]) Get(index int) (V, error) {
	if index < 0 || index >= len(l.value) {
		return *new(V), fmt.Errorf("index out of range")
	}
	return l.value[index], nil
}

func (l *List[V]) Set(index int, value V) {
	delete(l.maps, l.value[index])
	l.value[index] = value

	l.maps[value] = struct{}{}
}

func (l *List[V]) Del(index int) {
	delete(l.maps, l.value[index])
	l.value = append(l.value[:index], l.value[index+1:]...)
	l.len--
}

func (l *List[V]) Insert(index int, value V) {
	delete(l.maps, l.value[index])
	pre := l.value[:index]
	after := l.value[index:]
	l.value = append(append(pre, value), after...)
	l.maps[value] = struct{}{}
	l.len++
}

func (l *List[V]) Index(value V) int {
	for i := range l.value {
		if l.value[i] == value {
			return i
		}
	}
	return -1
}

func (l *List[V]) Contains(value V) bool {

	_, ok := l.maps[value]
	return ok
}

func (l *List[V]) Values() []V {
	return l.value
}

func (l *List[V]) Range(f func(index int, value V) bool) {
	for i := range l.value {
		if !f(i, l.value[i]) {
			break
		}
	}
}

func (l *List[V]) Clear() {
	l.value = l.value[:0]
	l.len = 0
	l.maps = nil
}

func (l *List[V]) Copy() *List[V] {
	newList := NewList[V]()
	for i := range l.value {
		newList.Append(l.value[i])
	}
	newList.len = l.len
	newList.maps = l.maps
	return newList
}

func (l *List[V]) Swap(i, j int) {
	l.value[i], l.value[j] = l.value[j], l.value[i]
}
